home *** CD-ROM | disk | FTP | other *** search
/ BCI NET 2 / BCI NET 2.iso / archives / programming / asm / adisv1_3.lha / src / main.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-01-14  |  14.6 KB  |  540 lines

  1. /*
  2.  * Change history
  3.  * $Log:    main.c,v $
  4.  * Revision 3.0  93/09/24  17:54:06  Martin_Apel
  5.  * New feature: Added extra 68040 FPU opcodes
  6.  * 
  7.  * Revision 2.3  93/07/18  22:56:07  Martin_Apel
  8.  * *** empty log message ***
  9.  * 
  10.  * Revision 2.2  93/07/11  21:38:36  Martin_Apel
  11.  * Major mod.: Deleted -ce option
  12.  * 
  13.  * Revision 2.1  93/07/10  13:06:59  Martin_Apel
  14.  * Major mod.: Added full jump table support. Seems to work quite well
  15.  * 
  16.  * Revision 2.0  93/07/01  11:54:11  Martin_Apel
  17.  * *** empty log message ***
  18.  * 
  19.  * Revision 1.23  93/07/01  11:41:05  Martin_Apel
  20.  * 
  21.  * Revision 1.22  93/06/19  19:01:28  Martin_Apel
  22.  * Bug fix: Upon non-FPU disassembly the first opcodes in the opcode table
  23.  *          were marked illegal. 
  24.  * 
  25.  * Revision 1.21  93/06/19  12:11:11  Martin_Apel
  26.  * Major mod.: Added full 68030/040 support
  27.  * 
  28.  * Revision 1.20  93/06/16  20:28:45  Martin_Apel
  29.  * Minor mod.: Removed #ifdef FPU_VERSION and #ifdef MACHINE68020
  30.  * Minor mod.: Added variables for 68030 / 040 support
  31.  * 
  32.  * Revision 1.19  93/06/06  13:46:58  Martin_Apel
  33.  * Minor mod.: Replaced first_pass and read_symbols by pass1, pass2, pass3
  34.  * 
  35.  * Revision 1.18  93/06/06  00:12:16  Martin_Apel
  36.  * Major mod.: Added support for library/device disassembly (option -dl)
  37.  * 
  38.  * Revision 1.17  93/06/04  11:51:22  Martin_Apel
  39.  * New feature: Added -ln option for generation of ascending label numbers
  40.  * 
  41.  * Revision 1.16  93/06/03  20:28:23  Martin_Apel
  42.  * New feature: Added -a switch to generate comments for file offsets
  43.  * 
  44.  * Revision 1.15  93/06/03  18:34:36  Martin_Apel
  45.  * Minor mod.: Table size for symbol table is now derived from the size of
  46.  *             the load file instead of from the sum of the hunk sizes
  47.  * Minor mod.: Remove temporary files upon exit (even with CTRL-C)
  48.  * 
  49.  */
  50.  
  51. #include <stdio.h>
  52. #include <stdlib.h>
  53. #include <string.h>
  54. #ifdef __GNUC__
  55. #include <sys/stat.h>
  56. #include <signal.h>
  57. #else
  58. #ifdef _DCC
  59. #include <sys/stat.h>
  60. #else
  61. #include <stat.h>
  62. #endif
  63. #endif
  64. #include "defs.h"
  65.  
  66. static char rcsid [] = "$Id: main.c,v 3.0 93/09/24 17:54:06 Martin_Apel Exp $";
  67.  
  68. PRIVATE void Usage (void)
  69.  
  70. {
  71. puts ("Usage: ADis [options] filename");
  72. puts ("");
  73. puts ("  Options is one of the following");
  74. puts ("     -a                               add absolute offset in file as comment");
  75. puts ("     -b num                           set buffersize for file buffers in KB");
  76. puts ("                                      default: 10 KB");
  77. puts ("     -c2                              enable 68020 instruction disassembly");
  78. puts ("     -c3                              enable 68030 instruction disassembly");
  79. puts ("     -c4                              enable 68040 instruction disassembly");
  80. puts ("     -c8                              enable 68881 instruction disassembly");
  81. puts ("                                      (only in conjunction with -c2, -c3, -c4)");
  82. #ifdef AMIGA
  83. puts ("     -dl                              disassemble as library (or device)");
  84. #endif
  85. puts ("     -fs                              put hunks in a single file");
  86. puts ("     -fm                              put each hunk in a separate file");
  87. puts ("     -i                               print addresses where illegal");
  88. puts ("                                      instructions were found");
  89. puts ("     -lc hex_address                  disassemble as code");
  90. puts ("     -ld hex_address                  disassemble as data");
  91. puts ("     -ln                              name labels with ascending numbers");
  92. puts ("                                      instead of code addresses");
  93. puts ("     -ml                              disassemble using large memory model");
  94. puts ("     -ms[base_offset]                 attempt to address code and ");
  95. puts ("                                      data relative to a4 (default 0x7ffe)");
  96. puts ("     -o outfilename                   filename of output file");
  97. puts ("                                      default: <filename>.dec");
  98. puts ("     -q                               quick disassembly, no labels");
  99. puts ("                                      no data recognition in code segments");
  100. puts ("     -v                               verbose");
  101. puts ("");
  102. exit (0);
  103. }
  104.  
  105. #define NEXT_OPT continue
  106.  
  107. void parse_args (int argc, char *argv [])
  108.  
  109. /* Possible parameters are:
  110.     filename                         input file name
  111.     -ms[base_offset]                 attempt to address code and
  112.                                      data relative to a4 (default 0x7ffe)
  113.     -ml                              disassemble using large memory model
  114.     -c2                              enable 68020 instruction disassembly
  115.     -c3                              enable 68030 instruction disassembly
  116.     -c4                              enable 68040 instruction disassembly
  117.     -c8                              enable 68881 instruction disassembly
  118.     -dl                              disassemble as library (or device)
  119.     -lc hex_address                  disassemble as code
  120.     -ld hex_address                  disassemble as data
  121.     -ln                              name labels with ascending numbers
  122.                                      instead of code addresses
  123.     -fs                              put hunks in a single file
  124.     -fm                              put each hunk in a separate file
  125.     -o outfilename                   filename of output file
  126.                                      default: <filename>.dec
  127.     -q                               quick disassembly, no labels
  128.                                      no data recognition in code segments
  129.     -b  num                          set buffersize for file buffers in KB
  130.                                      default: 10 KB
  131.     -i                               print addresses where illegal
  132.                                      instructions were found
  133.     -v                               verbose
  134.     -a                               add absolute offset in file as comment
  135. */
  136. {
  137. int i;
  138. ULONG address;
  139.  
  140. if (argc < 2)
  141.   Usage ();
  142.  
  143. output_filename [0] = 0;
  144. for (i = 1; i < argc; i++)
  145.   {
  146.   if (*argv [i] == '-')
  147.     {
  148.     switch (*(argv [i] + 1))
  149.       {
  150.       case 'm': /* Memory model to be used */
  151.                 switch (*(argv [i] + 2))
  152.                   {
  153.                   case 's':
  154.                     try_small = TRUE;
  155.                     if (*(argv [i] + 3) != 0)
  156.                       {
  157.                       if (sscanf (argv [i] + 3, "%lx", &a4_offset) != 1)
  158.                         {
  159.                         fprintf (stderr, "Invalid base for a4 relative addressing");
  160.                         ExitADis ();
  161.                         }
  162.                       }
  163.                     NEXT_OPT;
  164.                   case 'l': 
  165.                     try_small = FALSE;
  166.                     NEXT_OPT;
  167.                   }
  168.                 break;
  169.       case 'c': /* For which processor to generate output */
  170.                 switch (*(argv [i] + 2))
  171.                   {
  172.                   case '4': mc68040 = TRUE;
  173.                             mc68881 = TRUE;
  174.                   case '3': mc68030 = TRUE;
  175.                   case '2': mc68020 = TRUE;
  176.                             ext_68020_modes = TRUE;
  177.                             NEXT_OPT;
  178.                   case '8': mc68881 = TRUE;
  179.                             NEXT_OPT;
  180.                   }
  181.                 break;
  182. #ifdef AMIGA
  183.       case 'd': if (*(argv [i] + 2) != 'l')
  184.                   break;
  185.                 disasm_as_lib = TRUE;
  186.                 NEXT_OPT;
  187. #endif
  188.       case 'f': /* Whether to put the hunks in a single file or not */
  189.                 switch (*(argv [i] + 2))
  190.                   {
  191.                   case 's': user_wants_single_file = TRUE;
  192.                             NEXT_OPT;
  193.                   case 'm': user_wants_separate_files = TRUE;
  194.                             NEXT_OPT;
  195.                   }
  196.                 break;
  197.       case 'o': strcpy (output_filename, argv [++i]);
  198.                 NEXT_OPT;
  199.       case 'b': buf_size = atoi (argv [++i]) * 1024L;
  200.                 NEXT_OPT;
  201.       case 'v': verbose = TRUE;
  202.                 NEXT_OPT;
  203.       case 'i': print_illegal_instr_address = TRUE;
  204.                 NEXT_OPT;
  205.       case 'l': /* labels */
  206.                 switch (*(argv [i] + 2))
  207.                   {
  208.                   case 'c': 
  209.                     if (sscanf (argv [++i], "%lx", &address) != 1)
  210.                       {
  211.                       fprintf (stderr, "Invalid address for code label");
  212.                       ExitADis ();
  213.                       }
  214.                     if (address & 1)
  215.                       {
  216.                       fprintf (stderr, "Code labels not allowed on odd addresses");
  217.                       ExitADis ();
  218.                       }
  219.                     predefine_label (address, ACC_CODE);
  220.                     NEXT_OPT;
  221.                   case 'd': 
  222.                     if (sscanf (argv [++i], "%lx", &address) != 1)
  223.                       {
  224.                       fprintf (stderr, "Invalid address for data label");
  225.                       ExitADis ();
  226.                       }
  227.                     predefine_label (address, ACC_DATA);
  228.                     NEXT_OPT;
  229.                   case 'n':
  230.                     ascending_label_numbers = TRUE;
  231.                     NEXT_OPT;
  232.                   }
  233.                 break;
  234.       case 'q': disasm_quick = TRUE;
  235.                 NEXT_OPT;
  236.       case 'a': add_file_offset = TRUE;
  237.                 NEXT_OPT;
  238.  
  239.       }
  240.     fprintf (stderr, "ERROR: Invalid option '%s'\n", argv [i]);
  241.     Usage ();
  242.     }
  243.   else if (input_filename == 0)
  244.     input_filename = argv [i];
  245.   else
  246.     {
  247.     fprintf (stderr, "ERROR: Only one program can be disassembled at a time\n");
  248.     Usage ();
  249.     }
  250.   }
  251. }
  252.  
  253.  
  254. void open_files (void)
  255.  
  256. {
  257. /* This opens only the input file, but already allocates the buffer 
  258.    for the output file */
  259.  
  260. in_buf = get_mem (buf_size);
  261. out_buf = get_mem (buf_size);
  262.  
  263. if ((in = fopen (input_filename, "r")) == 0)
  264.   {
  265.   fprintf (stderr, "Couldn't find input file\n");
  266.   ExitADis ();
  267.   }
  268. setvbuf (in, in_buf, _IOFBF, buf_size);
  269. }
  270.  
  271.  
  272. void close_files (void)
  273.  
  274. {
  275. if (in)
  276.   fclose (in);
  277. if (out)
  278.   fclose (out);
  279. if (in_buf)
  280.   release_mem (in_buf);
  281. if (out_buf)
  282.   release_mem (out_buf);
  283. if (tmp_f)
  284.   fclose (tmp_f);
  285. }
  286.  
  287.  
  288. void open_output_file (void)
  289.  
  290. {
  291. char open_mode [2] = "w";
  292. char act_outname [200];
  293.  
  294. if (out != NULL)
  295.   return;
  296.  
  297. if (single_file)
  298.   {
  299.   if (output_filename [0] == 0)
  300.     strcat (strcpy (act_outname, input_filename), ".dec");
  301.   else
  302.     strcpy (act_outname, output_filename);
  303.  
  304.   if (current_hunk != 0)
  305.     open_mode [0] = 'a';           /* open for appending */
  306.   }
  307. else
  308.   {
  309.   if (output_filename [0] == 0)  
  310.     sprintf (act_outname, "%s.dec.%d", input_filename, current_hunk + 1);
  311.   else
  312.     sprintf (act_outname, "%s.%d", output_filename, current_hunk + 1);    
  313.   }
  314.  
  315.  
  316. if ((out = fopen (act_outname, &(open_mode [0]))) == 0)
  317.   {
  318.   fprintf (stderr, "Couldn't open output file\n");
  319.   ExitADis ();
  320.   }
  321. setvbuf (out, out_buf, _IOFBF, buf_size);
  322.  
  323. if (mc68020)
  324.   put ("                    MACHINE        MC68020\n");
  325. if (mc68881)
  326.   put ("                    MC68881\n");
  327. }
  328.  
  329.  
  330. void close_output_file (void)
  331.  
  332. {
  333. #ifdef DEBUG
  334. if (out == NULL)
  335.   {
  336.   fprintf (stderr, "INTERNAL ERROR: close_output_file: Trying to close closed file\n");
  337.   ExitADis ();
  338.   }
  339. #endif
  340.  
  341. if (!single_file || current_address == total_size)
  342.   {
  343.   put ("\n                    END\n");
  344.   fclose (out);
  345.   out = NULL;
  346.   }
  347. }
  348.  
  349.  
  350. void main (int argc, char *argv [])
  351.  
  352. {
  353. struct stat status;
  354.  
  355. #ifdef __GNUC__
  356.   signal (SIGINT, ExitADis);
  357. #endif
  358.  
  359. print_version ();
  360. parse_args (argc, argv);
  361. open_files ();
  362. stat (input_filename, &status);
  363. init_ref_table (status.st_size);
  364.  
  365. if (!mc68881)
  366.   {
  367.   int i;
  368.   for (i = 0; mc68881_disabled [i] != 0; i++)
  369.     mark_entry_illegal ((int)(mc68881_disabled [i]));
  370.   }
  371. if (!mc68020)
  372.   {
  373.   int i;
  374.   for (i = 0; mc68020_disabled [i] != 0; i++)
  375.     mark_entry_illegal ((int)(mc68020_disabled [i]));
  376.  
  377.   /* Disable extended addressign modes for TST instruction */
  378.   for (i = (0x4a00 >> 6); i <= (0x4a80 >> 6); i++)
  379.     {
  380.     opcode_table [i].modes = 0xfd;
  381.     opcode_table [i].submodes = 0x0f;
  382.     }
  383.   }
  384.  
  385. if (!mc68030)
  386.   {
  387.   int i;
  388.   for (i = 0; mc68030_disabled [i] != 0; i++)
  389.     mark_entry_illegal ((int)(mc68030_disabled [i]));
  390.   }
  391.  
  392. if (!mc68040)
  393.   {
  394.   int i;
  395.   for (i = 0; mc68040_disabled [i] != 0; i++)
  396.     mark_entry_illegal ((int)(mc68040_disabled [i]));
  397.   }
  398.  
  399. pass1 = TRUE;
  400. pass2 = pass3 = FALSE;
  401.  
  402. if (verbose)
  403.   puts ("Reading relocation and symbol information...");
  404.  
  405. if (!readfile ())
  406.   {
  407.   fprintf (stderr, "ERROR: Couldn't disassemble file\n");
  408.   ExitADis ();
  409.   }
  410.  
  411. /* The only thing I'm sure about right now is, that the first address in the
  412.    file has to be executable */
  413. enter_ref (0L, 0L, ACC_CODE);
  414. add_predefined_labels ();
  415.  
  416.  
  417. pass1 = FALSE;
  418. pass2 = TRUE;
  419. if (!disasm_quick)
  420.   {
  421.   rewind (in);
  422.   if (verbose)
  423.     puts ("Analyzing...");
  424.  
  425.   if (!readfile ())
  426.     {
  427.     fprintf (stderr, "ERROR: Couldn't disassemble file\n");
  428.     ExitADis ();
  429.     }
  430.   if (ascending_label_numbers)
  431.     assign_label_names ();
  432.   }
  433.  
  434. if (!user_wants_single_file && 
  435.     (num_code_hunks > 1 || num_data_hunks > 1 || num_bss_hunks > 1 ||
  436.     user_wants_separate_files))
  437.   single_file = FALSE;
  438.  
  439. rewind (in);
  440. pass2 = FALSE;
  441. pass3 = TRUE;
  442. if (verbose)
  443.   puts ("Disassembling...");
  444.  
  445. if (!readfile ())
  446.   {
  447.   fprintf (stderr, "ERROR: Couldn't disassemble file\n");
  448.   ExitADis ();
  449.   }
  450.  
  451. free_jmptab_list ();
  452. kill_ref_table ();
  453. close_files ();
  454. delete_tmp_files ();
  455. exit (0);
  456. }
  457.  
  458.  
  459. void ExitADis (void)
  460.  
  461. {
  462. free_jmptab_list ();
  463. kill_ref_table ();
  464. close_files ();
  465. delete_tmp_files ();
  466. fprintf (stderr, "ADis aborted...\n");
  467. exit (1);
  468. }
  469.  
  470. #ifdef AZTEC_C
  471. void _abort (void)
  472.  
  473. {
  474. ExitADis ();
  475. }
  476. #endif
  477.  
  478. #ifdef DEBUG
  479. void check_consistency ()
  480.  
  481. {
  482. int i;
  483. struct opcode_entry *oe;
  484.  
  485. for (i = 0; i <= 1055; i++)
  486.   {
  487.   oe = &opcode_table [i];
  488.   if (oe->handler == dual_op)
  489.     continue;
  490.   if (oe->handler == move)
  491.     continue;
  492.   if (oe->handler == branch)
  493.     continue;
  494.   if (oe->handler == illegal)
  495.     continue;
  496.   if (oe->handler == op_l)
  497.     continue;
  498.   if (oe->handler == op_w)
  499.     continue;
  500.   if (oe->handler == quick)
  501.     continue;
  502.   if (oe->handler == single_op)
  503.     continue;
  504.   if (oe->handler == shiftreg)
  505.     continue;
  506.   if (oe->handler == bit_reg)
  507.     continue;
  508.   if (oe->handler == dbranch)
  509.     continue;
  510.   if (oe->handler == immediate)
  511.     continue;
  512.   if (oe->handler == moveq)
  513.     continue;
  514.   if (oe->handler == bit_mem)
  515.     continue;
  516.   if (oe->handler == cmpm)
  517.     continue;
  518.   if (oe->handler == end_single_op)
  519.     continue;
  520.   if (oe->handler == exg)
  521.     continue;
  522.   if (oe->handler == movem)
  523.     continue;
  524.   if (oe->handler == movep)
  525.     continue;
  526.   if (oe->handler == movesrccr)
  527.     continue;
  528.   if (oe->handler == restrict)
  529.     continue;
  530.   if (oe->handler == scc)
  531.     continue;
  532.   if (oe->handler == special)
  533.     continue;
  534.   if (oe->handler == srccr)
  535.     continue;
  536.   fprintf (stderr, "Invalid opcode handler found at entry %d\n", i);
  537.   }
  538. }
  539. #endif
  540.